<template>
  <transition name="ent-fade">
    <div v-if="visible" class="fixed top-4 right-4 z-50 max-w-md w-full overflow-hidden shadow-enterprise-lg animate-slide-in" role="alert">
      <div :class="notificationClasses">
        <div class="flex items-start">
          <div class="flex-shrink-0 mt-0.5">
            <svg v-if="type === 'info'" class="h-5 w-5 text-blue-500 dark:text-blue-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
              <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd" />
            </svg>
            <svg v-else-if="type === 'success'" class="h-5 w-5 text-green-500 dark:text-green-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
              <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
            </svg>
            <svg v-else-if="type === 'warning'" class="h-5 w-5 text-yellow-500 dark:text-yellow-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
              <path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
            </svg>
            <svg v-else-if="type === 'error'" class="h-5 w-5 text-red-500 dark:text-red-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
              <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
            </svg>
          </div>
          <div class="ml-3 w-0 flex-1">
            <p class="text-sm font-medium" :class="titleClasses">{{ title }}</p>
            <p class="mt-1 text-sm" :class="messageClasses">{{ message }}</p>
          </div>
          <div class="ml-4 flex-shrink-0 flex">
            <button
              @click="close"
              class="inline-flex rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-primary-400 focus:ring-offset-2"
            >
              <span class="sr-only">关闭</span>
              <svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
                <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
              </svg>
            </button>
          </div>
        </div>
      </div>
      <!-- 进度条 -->
      <div v-if="duration" class="h-1 bg-gray-200 dark:bg-gray-700">
        <div 
          :class="progressClasses" 
          :style="{ width: `${progress}%` }"
          class="h-full transition-all duration-100 ease-linear"
        ></div>
      </div>
    </div>
  </transition>
</template>

<script>
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'

export default {
  name: 'Notification',
  props: {
    title: {
      type: String,
      default: ''
    },
    message: {
      type: String,
      default: ''
    },
    type: {
      type: String,
      default: 'info',
      validator: value => ['info', 'success', 'warning', 'error'].includes(value)
    },
    duration: {
      type: Number,
      default: 3000
    }
  },
  emits: ['close'],
  setup(props, { emit }) {
    const visible = ref(true)
    const progress = ref(100)
    let timeoutId = null
    let intervalId = null
    
    const notificationClasses = computed(() => {
      return {
        'ent-notification-info': props.type === 'info',
        'ent-notification-success': props.type === 'success',
        'ent-notification-warning': props.type === 'warning',
        'ent-notification-error': props.type === 'error',
      }
    })
    
    const titleClasses = computed(() => {
      return {
        'text-blue-800 dark:text-blue-300': props.type === 'info',
        'text-green-800 dark:text-green-300': props.type === 'success',
        'text-yellow-800 dark:text-yellow-300': props.type === 'warning',
        'text-red-800 dark:text-red-300': props.type === 'error',
      }
    })
    
    const messageClasses = computed(() => {
      return {
        'text-blue-700 dark:text-blue-200': props.type === 'info',
        'text-green-700 dark:text-green-200': props.type === 'success',
        'text-yellow-700 dark:text-yellow-200': props.type === 'warning',
        'text-red-700 dark:text-red-200': props.type === 'error',
      }
    })
    
    const progressClasses = computed(() => {
      return {
        'bg-blue-500': props.type === 'info',
        'bg-green-500': props.type === 'success',
        'bg-yellow-500': props.type === 'warning',
        'bg-red-500': props.type === 'error',
      }
    })
    
    const startTimer = () => {
      if (props.duration) {
        // 自动关闭计时器
        timeoutId = setTimeout(() => {
          close()
        }, props.duration)
        
        // 进度条动画
        const updateInterval = 30 // 每30ms更新一次
        const steps = props.duration / updateInterval
        const stepSize = 100 / steps
        
        progress.value = 100
        intervalId = setInterval(() => {
          progress.value = Math.max(0, progress.value - stepSize)
          if (progress.value <= 0) {
            clearInterval(intervalId)
          }
        }, updateInterval)
      }
    }
    
    const resetTimer = () => {
      if (timeoutId) {
        clearTimeout(timeoutId)
        timeoutId = null
      }
      if (intervalId) {
        clearInterval(intervalId)
        intervalId = null
      }
      
      startTimer()
    }
    
    const close = () => {
      visible.value = false
      
      if (timeoutId) {
        clearTimeout(timeoutId)
        timeoutId = null
      }
      
      if (intervalId) {
        clearInterval(intervalId)
        intervalId = null
      }
      
      emit('close')
    }
    
    watch(() => props.title, resetTimer)
    watch(() => props.message, resetTimer)
    
    onMounted(() => {
      startTimer()
    })
    
    onBeforeUnmount(() => {
      if (timeoutId) {
        clearTimeout(timeoutId)
      }
      if (intervalId) {
        clearInterval(intervalId)
      }
    })
    
    return {
      visible,
      progress,
      notificationClasses,
      titleClasses,
      messageClasses,
      progressClasses,
      close,
      type: computed(() => props.type)
    }
  }
}
</script>

<style scoped>
.ent-fade-enter-active,
.ent-fade-leave-active {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.ent-fade-enter-from {
  transform: translateX(100%);
  opacity: 0;
}

.ent-fade-leave-to {
  transform: translateX(100%);
  opacity: 0;
}
</style>
